最好全部用具名常量代替,唯一能出现的字面量就是0和1。这样做的好处是好维护。以后需要修改的时候,只要修改一处就行。
直接写死数值,是不好的做法。
public void foo() {
for (int i = 0; i < 99; i++) {
// do something
}
}
使用具名常量是更稳妥的做法。
private final int MAX_VALUE = 99;
public void foo() {
for (int i = 0; i < MAX_VALUE; i++) {
// do something
}
}
下面直接写死文字字面量也不好。
BufferedReader br = new BufferedReader(new FileReader(new File("/Users/Wei/java/Exercise1.java")));
要用具名常量或者至少也要声明一个变量来替代。
String path = "/Users/Wei/java/Exercise1.java";
BufferedReader br = new BufferedReader(new FileReader(new File(path)));
7 / 10 = 0
,不等于0.7
。
浮点数的计算结果是不精确的。
0.1 + 0.1 = 0.2
0.1 + 0.1 + 0.1 = 0.30000000000000004
原因是,十进制的小数,用二进制表示会变成无限循环小数。只有特定小数才能转换成有限二进制小数,例如,
0.625 转成二进制是:0.101
0.4 转成二进制是:0.011001100...无限循环
0.1 转成二进制是:0.00011001100110011...无限循环
下面这个比较的结果,10个0.1相加并不等于1.0。
double nominal = 1.0;
double sum = 0.0;
for (int i = 0; i < 10; i++) {
sum += 0.1;
}
if ( nominal == sum ) {
System.out.println("Numbers are the same!");
} else {
System.out.println("Numbers are not the same!");
}
在一些需要确保精确的场景下,可以换用二进制编码的十进制(binary coded decimal, BCD)变量来解决。是在没有,也可以自己写一个整型变量变成整型变量的库。
这点在具名具名常量这部分已经说了。声明一个变量,或者具名常量,推迟变量和数据绑定的时机,降低程序的耦合,增加灵活性。
尽量考虑国际化的因素。而且编码方式也要尽量统一。比如UTF-8。
下面这段代码可读性差,
if ( (elementIndex < 0) || (MAX_ELEMENTS < elementIndex) || (elementIndex == lastElementIndex) ) {
// do something
}
比较好的做法是,把局部性的判断条件声明为布尔变量,可以将判断的意图描述地更清晰,更不容易出错。
boolean finished = (elementIndex < 0) || (MAX_ELEMENTS < elementIndex);
boolean repeatedEntry = (elementIndex == lastElementIndex);
if ( finished || repeatedEntry) {
// do something
}
下面这个绝对是糟糕的代码,用1代表红色,然后还需要注释来解释。
/**
* 1 = red
* 2 = blue
* 3 = green
*/
if (chosenColor = 1) {
// ...
}
这时候用枚举就会让事情变得非常好懂,
enum Color { RED, BLUE, GREEN }
if (chosenColor = Color.RED) {
// ...
};
这条在Java可能并不太适用。
enum Color { FIRST_COLOR, RED, BLUE, GREEN, LAST_COLOR }
适用顺序访问更可靠。比如Collection里的Iterator。每次都从头开始遍历,可以减少失误的可能。而且每次调用next()都可以用hasNext()进行判断。
显然容器能做的更多,而且更健壮。